home *** CD-ROM | disk | FTP | other *** search
- /*****
- *
- * Grant's CGI Shell (Common Grant Interface :-)
- * http://arpp1.carleton.ca/grant/mac/grantscgi.html
- *
- * main.c
- *
- * by Grant Neufeld
- *
- * Copyright ©1995 by Grant Neufeld
- *
- * http://arpp1.carleton.ca/grant/
- * gneufeld@ccs.carleton.ca
- * grant@acm.org
- *
- * This source may be freely used as long as the copyright notice is kept in the source.
- * I ask that you let me know of any enhancements (read: bug fixes) to this code.
- * I would also like copies of (or discounts on) anything you produce using this code, please.
- *
- *****/
-
- #define __MainSegment__ 1
-
- #include "MyConfiguration.h"
-
- #include <string.h>
- #include <Threads.h>
- #if __profile__ && __MWERKS__
- #include <Profiler.h>
- #endif
-
- #include "compiler_stuff.h"
- #include "constants.h"
- #include "globals.h"
-
- #include "DebugUtil.h"
- #include "ErrorUtil.h"
- #include "EventUtil.h"
- #include "MemoryUtil.h"
- #include "MenuFunc.h"
- #include "Quit.h"
- #include "Startup.h"
-
-
- /*** LOCAL VARIABLES ***/
-
- static RgnHandle vTheMouseRgn;
-
-
- /*** LOCAL PROTOTYPES ***/
-
- static void mainEventLoop ( void );
- static void startupToolbox ( void );
- static Boolean initAppMemory ( void );
- static OSErr initStackGrow ( Size );
-
-
- /*** FUNCTIONS ***/
-
- /* Application entry point. */
- void
- main ( void )
- {
- /* Application is not set to quit */
- gQuit = false;
-
- /* Included here because of InitWindows() allocation of non-relocatable blocks.
- This needs to be done before any other code segments are loaded.
- IM:Processes 7-5 */
- /* initialize standard toolbox managers */
- startupToolbox ();
-
- /* Included here because of MoreMasters() allocation of non-relocatable blocks.
- This needs to be done before any other code segments are loaded.
- IM:Processes 7-5 */
- if ( !( initAppMemory () ) )
- {
- /* inform user of insufficient memory */
- ErrorStartup ( kerrStartupMemory );
- ExitToShell ();
- }
-
- #if __profile__ && __MWERKS__
- gProfileOn = !( ProfilerInit ( collectDetailed, bestTimeBase, 20, 5 ) );
- #endif
-
- StartupApplication ();
-
- /* main loop for handling system and user events */
- mainEventLoop ();
-
- #if __profile__ && __MWERKS__
- if ( gProfileOn )
- {
- ProfilerDump("\p" kProfileNameStr "-" kProcessorString ".prof");
- ProfilerTerm();
- }
- #endif
-
- ExitToShell ();
- } /* main */
-
-
- /* main loop for handling system and user events.
- Continuously loop until application is set to quit. */
- static void
- mainEventLoop ( void )
- {
- #if !(kCompileWithQuitOnLowMemory)
- OSErr theErr;
- #endif
- Boolean eventResult;
- EventRecord event;
- short loopCounter;
-
- while ( !gQuit )
- {
- #if !(kCompileWithQuitOnLowMemory)
- /* if app doesn't quit on low memory, may need to recover emrgncy mem */
- /* IM-Memory: 1-48 */
- if ( !IsEmergencyMemAvail() )
- {
- theErr = RecoverEmergencyMemory ();
-
- if ( theErr != noErr )
- {
- gQuit = true;
- }
- }
- #endif
-
- #if kCompileWithThreadsOptional
- if ( gHasThreadMgr )
- #endif
- {
- /* Yield more often if there are any sub-threads. The 'more often'
- depends on how many sub-threads there are */
- if ( gThreadTotal > 1 )
- {
- for ( loopCounter = nil; loopCounter < gThreadTotal; loopCounter++ )
- {
- YieldToAnyThread ();
- }
- }
- else
- {
- /* just yield once if there are no sub-threads, or only one */
- YieldToAnyThread ();
- }
- }
-
- if ( !gQuit )
- {
- /* wait until the next event */
- eventResult = WaitNextEvent ( everyEvent, &event, gSleepTicks, nil );
-
- if ( eventResult )
- {
- /* if there is an event other than null */
- /* clean up the menus */
- adjustMenus ();
-
- /* figure out which event and process it */
- switch ( event.what )
- {
- case kHighLevelEvent:
- doHighLevelEvent ( &event );
- break;
-
- #if kCompileWithForeground
-
- case mouseDown:
- doMouseDown ( &event );
- break;
-
- case mouseUp:
- doMouseUp ( &event );
- break;
-
- case keyDown:
- doKeyDown ( &event );
- break;
-
- case autoKey:
- doAutoKey ( &event );
- break;
-
- /* typically not sent to the application. IM-MTE: 2-28 */
- case keyUp:
- doKeyUp ( &event );
- break;
-
- case activateEvt:
- doActivateEvent ( &event );
- break;
-
- case updateEvt:
- doUpdateEvent ( &event );
- break;
-
- /* suspend or resume */
- case osEvt:
- doOsEvt ( &event );
- break;
-
- /* disk inserted */
- case diskEvt:
- doDiskEvt ( &event );
- break;
-
- #endif /* kCompileWithForeground */
-
- default:
- doIdle ( &event );
- break;
- }
- }
- else
- {
- /* not a handled event, or event is null */
- doIdle ( &event );
- }
- }
-
- if ( gQuit )
- {
- QuitPrepare ( true );
- }
- }
- } /* mainEventLoop */
-
-
- /*** INITIALIZATION ***/
- #pragma mark -
-
- /* initialize standard toolbox managers */
- static void
- startupToolbox ( void )
- {
- InitGraf ( (Ptr)(&qd.thePort) ); /* InitGraf must be first */
-
- #if kCompileWithForeground
- /* initialize interface managers */
-
- InitFonts ();
- InitWindows ();
- InitMenus (); /* InitMenus must be after InitWindows */
- FlushEvents ( everyEvent, nil ); /* IM-MTE: 2-93 */
- TEInit ();
- InitDialogs ( nil ); /* InitDialogs must be after TEInit */
- InitCursor ();
-
- #endif
- } /* startupToolbox */
-
-
- /* Return true if memory initialization was successful. */
- static Boolean
- initAppMemory ( void )
- {
- short mstrPtrsAllocated;
- long freeMemAvail;
- Boolean success;
- Handle sacrificeHandle;
-
- #if !(kCompileWithForeground)
- /* Background only apps get a default 8K stack instead of 24K.
- Increase stack size if set to background only - just to be on the safe side */
- success = ( initStackGrow(16384) == noErr );
- #endif
-
- /* NOTE: MaxApplZone must be called before any memory is allocated by threads
- other than the main (application) thread. */
- /* maximize available memory in the application heap */
- MaxApplZone ();
-
- freeMemAvail = FreeMem ();
-
- if ( freeMemAvail < kMinSegSize )
- {
- /* not enough memory for application to run */
- success = false;
- }
- else
- {
- /* to avoid memory fragmentation, allocate master pointers at bottom of heap */
- for ( mstrPtrsAllocated = 0; mstrPtrsAllocated < kMoreMasterCalls; mstrPtrsAllocated++ )
- {
- MoreMasters ();
- }
-
- success = InitializeEmergencyMemory ( nil );
- }
-
- /* Allocate a 1K memory block, force it to the top of the heap, and lock it.
- This block is not used for anything - it is put at the top of the heap
- as a sacrifice because sometimes MacSLIP's VBL task trashes the end of
- the heap.
- from "NewsWatcher" 'newswatcher.c' */
- sacrificeHandle = MyNewHandle ( 1024, nil );
- if ( sacrificeHandle != nil )
- {
- HLockHi ( sacrificeHandle );
- }
-
- return success;
- } /* initAppMemory */
-
-
- /* */
- static OSErr
- initStackGrow ( Size increaseSize )
- {
- OSErr theErr;
-
- my_assert ( (increaseSize % 1024) == nil, "\pinitStackGrow: size is not multiple of 1024" );
-
- /* Increase the stack size by lowering the heap limit. */
- SetApplLimit ( (Ptr)(((unsigned long)GetApplLimit()) - increaseSize) );
- theErr = MemError ();
-
- return theErr;
- } /* initStackGrow */
-
-
- /*** EOF ***/
-